package class06_heap;


public class Test03_HeapSort {


    /**
     * 堆排序：
     * 给定一个无序数组，通过堆进行排序
     */
    public void heapSort(int[] arr) {
        // 边界条件
        if (arr == null || arr.length < 2) {
            return;
        }
        // 将数组转为一个大根堆结构
        //　通过heapify 将无序数组转为一个大根堆
        int heapSize = arr.length;
        for (int i = heapSize - 1; i >= 0; i--) {
            heapify(arr, i, heapSize);
        }
        // 不断将堆顶的元素放到最后，并缩短堆的长度，直至 heapSize = 0;
        swap(arr, 0, --heapSize);
        while (heapSize > 0) {
            heapify(arr, 0, heapSize);
            swap(arr, 0, --heapSize);
        }
    }

    /**
     * 将index值往下down,调整为大根堆
     *
     * @param arr
     * @param index
     * @param heapSize
     */
    private void heapify(int[] arr, int index, int heapSize) {
        // 左节点
        int left = index * 2 + 1;
        // 当 index 小于 heapSize 时，开始往下down,当 index 的值大于其子节点的值时，停止往下down
        while (left < heapSize) {
            // 比较出index的value 和其 两个子节点中value中谁的value大，并获取其索引
            int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
            largest = arr[index] > arr[largest] ? index : largest;
            // 表明index值就是最大值了
            if (index == largest) {
                break;
            }
            // index值和较大的进行交换后，并且index往下down
            swap(arr, index, largest);
            index = largest;
            left = index * 2 + 1;
        }


    }

    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
